package pipelinedemo

import (
	"sort"
	"math/rand"
	"time"
	"io"
	"encoding/binary"
	"bufio"
)

func ArraySource(sources []int) (chan int) {
	a := make(chan int)

	go func() {
		for _, v := range sources {
			a <- v
		}
		close(a)
		//chan用完关闭
	}()
	return a
}
func ArraySource_chan(sources []int) (<-chan int) {
	a := make(chan int)

	go func() {
		for _, v := range sources {
			a <- v
		}
		close(a)

		//chan用完关闭
	}()
	return a
}

//private 方法
func imMenSort(a <-chan int) (<-chan int) {
	out := make(chan int)
	go func() {
		arr := []int{}
		//读chan
		for v := range a {
			arr = append(arr, v)
		}
		sort.Ints(arr)
		//写入返回chan
		for _, v := range arr {
			out <- v
		}
		close(out)

	}()
	return out
}
func RandomIntValus(nums int) <-chan int {
	out := make(chan int)
	rand.Seed(time.Now().UnixNano())
	go func() {
		for i := 0; i < nums; i++ {
			out <- rand.Intn(100000000000)
		}
		close(out)
	}()
	//	close(out)
	return out
}
func ReadFile(reader io.Reader) <-chan int {
	reader = bufio.NewReader(reader)
	out := make(chan int)

	go func() {
		buffer := make([]byte, 8)
		for {
			n, err := reader.Read(buffer)
			if (err != nil) {
				err.Error()
				break
			} else {
				if (n > 0) {
					v := int(binary.BigEndian.Uint64(buffer))
					out <- v
				}
			}
		}
		close(out)
	}()
	return out
}
func WriteFile(writer io.Writer, in <-chan int) {
	writer = bufio.NewWriter(writer)
	for v := range in {
		buffer := make([]byte, 8)
		binary.BigEndian.PutUint64(buffer, uint64(v))
		writer.Write(buffer)
	}
}

//排序并合并
func MergeSortInMen(in1, in2 <-chan int) (<-chan int) {
	out := make(chan int)

	data1 := imMenSort(in1)
	data2 := imMenSort(in2)
	go func() {
		v1, ok1 := <-data1
		v2, ok2 := <-data2
		for ok1 || ok2 {
			if (!ok2) { //data2读完了
				out <- v1
				v1, ok1 = <-data1
			} else if (!ok1) { //data1读完了
				out <- v2
				v2, ok2 = <-data2
			} else {
				//谁小先入out,继续用下一个数据比较取最新
				if (v1 < v2) {
					out <- v1
					v1, ok1 = <-data1
				} else {
					out <- v2
					v2, ok2 = <-data2
				}
			}
		}
		close(out)
	}()
	return out
}
